package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.AipFaceTemplate;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.autoconfig.template.SmsTemplate;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.domain.User;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.UserInfoVo;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.utils.Constants;
import com.tanhua.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author LiKe
 * @date 2022/1/19 22:04
 */
@Service
public class UserService {
    private static String key = "CHECK_CODE_";
    @Autowired
    private SmsTemplate smsTemplate;//阿里云短信服务
    @Autowired
    private RedisTemplate<String,String> redisTemplate; //redis
    @DubboReference
    private UserApi userApi;//Dubbo远程调用user服务
    @DubboReference
    private UserInfoApi userInfoApi;//Dubbo远程调用userInfo服务
    @DubboReference
    private FriendApi friendApi;
    @DubboReference
    private UserLikeApi userLikeApi;
    @DubboReference
    private VisitorsApi visitorsApi;
    @Autowired
    private OssTemplate ossTemplate;//阿里云oss云存储
    @Autowired
    private AipFaceTemplate aipFaceTemplate;//百度人脸识别
    @Autowired
    private HuanXinTemplate huanXinTemplate;//环信
    @Autowired
    private UserFreezeService userFreezeService;
    /**
     * 发送短信验证码
     *
     * @param phone
     */
    public void sendCode(String phone) {
        //校验用户状态--------------------------
        User user = userApi.findByMobile(phone);
        if (user != null) {
            userFreezeService.checkUserStatus(1,user.getId());
        }
        //1.判断redis中是否有验证码
        String oldCode = redisTemplate.opsForValue().get(key + phone);
        if (StringUtils.isNotBlank(oldCode)){
            //1.1.缓存中有验证码 直接发送缓存中的未过期的验证码 不需要生成新的
            //调用阿里云发短信
            //smsTemplate.sendSms(phone,oldCode);
            System.out.println("code = "+oldCode);
            return;
        }

        //2.生成新验证码
        //String code = RandomStringUtils.randomNumeric(6);
        String code = "666666";
        System.out.println("code = "+code);
        //3.调用阿里云发短信
        //smsTemplate.sendSms(phone,code);
        //4.把验证码存到redis中
        redisTemplate.opsForValue().set(key + phone, code, 5, TimeUnit.MINUTES);
    }

    /**
     * 登录
     * @param mobile
     * @param code
     * @return
     */
    public Map login(String mobile, String code) {
        //1.根据phone为key 读取redis中的验证码
        String redisCode = redisTemplate.opsForValue().get(key + mobile);
        //2.如果验证码码为空||用户输入的验证码跟redis中的验证码不一致 就抛出异常
        if (StringUtils.isBlank(redisCode) || !code.equals(redisCode)){
            throw new RuntimeException("验证码错误！");
        }
        //2.1.验证成功 删除redis中的验证码
        redisTemplate.delete(key+mobile);
        //3.查询当前用户是否为新用户
        User user = userApi.findByMobile(mobile);
        boolean isNew = false;
        if (user==null) {
            //3.1.是新用户 添加新用户
            user = new User();
            user.setMobile(mobile);
            user.setPassword(DigestUtils.md5Hex(Constants.INIT_PASSWORD));
            Long id = userApi.save(user);
            user.setId(id);
            isNew = true;
            //3.2注册环信
            createHxUser(user);
        }
        //4.登录成功, 生成token
        Map<String,Object> tokenMap = new HashMap<>();
        tokenMap.put("id",user.getId());
        tokenMap.put("mobile",mobile);
        String token = JwtUtils.getToken(tokenMap);

        //5.返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("isNew", isNew);

        return result;
    }
    //注册环信用户
    public void createHxUser(User user) {
        //注册环信用户
        String hxUser = Constants.HX_USER_PREFIX + user.getId();
        huanXinTemplate.createUser(hxUser, Constants.INIT_PASSWORD);
        //探花用户信息关联环信用户信息
        user.setHxUser(hxUser);
        user.setHxPassword(Constants.INIT_PASSWORD);
        userApi.update(user);
    }

    /**
     * 保存用户信息
     * @param userInfo
     */
    public void save(UserInfo userInfo) {
        userInfoApi.save(userInfo);
    }

    /**
     * 更新用户头像
     * @param headPhoto
     * @param userId
     */
    public void updateHead(MultipartFile headPhoto, Long userId) throws IOException {
        //1.将图片上传到阿里云
        String urls = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        String imageUrl = urls.split("#")[0];
        String deleteUrl = urls.split("#")[1];
        //2.调用百度云进行人脸识别
        boolean detect = aipFaceTemplate.detect(imageUrl);
        //2.1如果不包含人脸 抛出异常
        if (!detect){
            //删除oss中垃圾头像
            ossTemplate.remove(deleteUrl);
            throw new BusinessException(ErrorResult.faceError());
        }else {
            //2.2 包含人脸，调用API更新
            UserInfo userInfo = new UserInfo();
            userInfo.setId(userId);
            userInfo.setAvatar(imageUrl);
            userInfoApi.update(userInfo);
        }
    }

    /**
     * 按id查询用户信息
     * @param userID
     * @return
     */
    public UserInfoVo fingById(Long userID) {
        //查询用户基本信息
        UserInfo userInfo = userInfoApi.findById(userID);
        //返回Vo对象
        UserInfoVo vo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo,vo);

        if(userInfo.getAge() != null) {
            vo.setAge(userInfo.getAge().toString());
        }

        return vo;
    }

    /**
     * 更新用户信息
     * @param userInfo
     */
    public void updateUser(UserInfo userInfo) {
        userInfoApi.update(userInfo);
    }

    /**
     * 验证验证码
     * @param code
     * @return
     */
    public Boolean checkCode(String code) {
        //1.根据phone为key 读取redis中的验证码
        String mobile = UserHolder.getMobile();
        String redisCode = redisTemplate.opsForValue().get(key + mobile);
        //2.如果验证码码为空||用户输入的验证码跟redis中的验证码不一致 就返回false
        if (StringUtils.isBlank(redisCode) || !code.equals(redisCode)){
            return false;
        }
        return true;
    }

    /**
     * 修改手机号
     * @param phone
     */
    public void updatePhone(String phone) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //dubbo远程调用userapi
        userApi.updatePhone(userId,phone);

    }
    //互相喜欢，喜欢，粉丝 - 统计
    public Map counts() {
        //互相喜欢-->好友
        Integer eachLoveCount = friendApi.findFriendCount(UserHolder.getUserId());
        //喜欢
        Integer loveCount = Math.toIntExact(redisTemplate.opsForSet().size(Constants.USER_LIKE_KEY + UserHolder.getUserId()));
        //粉丝
        Integer fanCount = userLikeApi.findFanCount(UserHolder.getUserId());
        Map<String,Integer> map = new HashMap();
        map.put("eachLoveCount",eachLoveCount);
        map.put("loveCount",loveCount);
        map.put("fanCount",fanCount+eachLoveCount);
        return map;
    }
    //查询翻页
    public PageResult page(int type, int page, int pagesize, String nickname) {
        PageResult pageResult = new PageResult(page,pagesize,0);
        switch (type){
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            case 4:
                //查询访客分页列表
                //保存最新查看访客列表的时间
                String redisKey = Constants.VISITORS_USER;
                String hashKey = String.valueOf(UserHolder.getUserId());
                long millis = System.currentTimeMillis();
                redisTemplate.opsForHash().put(redisKey,hashKey,String.valueOf(millis));

                List<Visitors> visitorsList = visitorsApi.findAll(page,pagesize,UserHolder.getUserId());
                if (CollUtil.isEmpty(visitorsList)) {
                    return new PageResult();
                }
                //4. 封装数据返回
                List<Long> vids = visitorsList.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());

                Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(vids, null);

                List<VisitorsVo> visitorsVoList = visitorsList.stream().map(visitors -> {
                    UserInfo userInfo = userInfoMap.get(visitors.getVisitorUserId());
                    return VisitorsVo.init(userInfo, visitors);
                }).collect(Collectors.toList());
                pageResult.setItems(visitorsVoList);
                break;
        }
        return pageResult;
    }
}
